﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using XSTDZ.ERP.Application.DataContracts;
using AutoMapper;
using XSTDZ.ERP.Domain.Models;
using XSTDZ.ERP.Core.Repositories;
using XSTDZ.ERP.Core.Generator;
using XSTDZ.ERP.Core.Specifications;

namespace XSTDZ.ERP.Application.Implements
{
    public class ClientServiceImpl : ApplicationServiceBase, IClientService
    {
        IRepository<ClientInfo> _clientRepository;
        IRepository<ClientLink> _clientItemRepository;
        IRepository<AddressArea> _addressAreaRepository;
        public ClientServiceImpl(IRepositoryContext repositoryContext, IRepository<ClientInfo> clientRepository, IRepository<ClientLink> clientItemRepository, IRepository<AddressArea> addressAreaRepository)
            : base(repositoryContext)
        {
            this._clientRepository = clientRepository;
            this._clientItemRepository = clientItemRepository;
            this._addressAreaRepository = addressAreaRepository;
        }

        public void AddClient(ClientLinkDto clientLinkDto)
        {
            var clientLink = Mapper.Map<ClientLinkDto, ClientLink>(clientLinkDto);
            clientLink.Id = (Guid)new SequentialIdentityGenerator().Next;
            clientLink.Init();
            this._clientItemRepository.Add(clientLink);
            this.Context.Commit();
        }

        public void AddClient(ClientInfoDto clientInfoDto)
        {
            var clientInfo = Mapper.Map<ClientInfoDto, ClientInfo>(clientInfoDto);
            clientInfo.Id = (Guid)new SequentialIdentityGenerator().Next;
            clientInfo.Init();
            this._clientRepository.Add(clientInfo);
            this.Context.Commit();
        }

        public void AddClient(IList<ClientLinkDto> clientLinkDtos)
        {
            var clientInfos = Mapper.Map<IList<ClientLinkDto>, IList<ClientLink>>(clientLinkDtos);
            clientInfos.Each(c=>{c.Id= (Guid)new SequentialIdentityGenerator().Next; c.Init();});
            this._clientItemRepository.Add(clientInfos);
            this.Context.Commit();
        }

        public void UpdateClient(ClientLinkDto clientLinkDto)
        {
            var clientLink = Mapper.Map<ClientLinkDto, ClientLink>(clientLinkDto);
            this._clientItemRepository.Update(clientLink.UpdateInit());
            this.Context.Commit();
        }

        public void UpdateClient( ClientInfoDto clientInfoDto)
        {
            var clientInfo = Mapper.Map<ClientInfoDto, ClientInfo>(clientInfoDto);
            this._clientRepository.Update(clientInfo);
            this.Context.Commit();
        }

        public void UpdateClient(IList<ClientLinkDto> clientLinkDtos)
        {
            var clientInfos = Mapper.Map<IList<ClientLinkDto>, IList<ClientLink>>(clientLinkDtos);
            this._clientItemRepository.Update(clientInfos);
            this.Context.Commit();
        }

        public IList<ClientInfoDto> GetClientInfos(int pageIndex, int pageSize,bool containDelete)
        {
            ISpecification<ClientInfo> spec = Specification<ClientInfo>.Eval(m=>1==1);
            if (!containDelete)
            {
                spec = Specification<ClientInfo>.Eval(m => m.Deleted != 1);
            }
            var orderby = new OrderByParameter<ClientInfo>(m => m.CreateTime, SortOrder.Descending);

            var clients = this._clientRepository.GetAll(spec, pageIndex, pageSize, new[] { orderby });
            return Mapper.Map<IList<ClientInfo>, IList<ClientInfoDto>>(clients.ToList());
        }

        public IList<ClientLinkDto> GetClientLinks(int pageIndex, int pageSize, bool containDelete)
        {
            ISpecification<ClientLink> spec = Specification<ClientLink>.Eval(m => 1 == 1);
            if (!containDelete)
            {
                spec = Specification<ClientLink>.Eval(m => m.Deleted != 1);
            }
            var orderby = new OrderByParameter<ClientLink>(m => m.CreateTime, SortOrder.Descending);

            var clients = this._clientItemRepository.GetAll(spec, pageIndex, pageSize, new[] { orderby });
            return Mapper.Map<IList<ClientLink>, IList<ClientLinkDto>>(clients.ToList());
        }


        public IList<ClientLinkDto> GetClientLinks(Guid clientId)
        {
            var orderby = new OrderByParameter<ClientLink>(m => m.CreateTime, SortOrder.Descending);
            var clients = this._clientItemRepository.GetAll(c=>c.ClientID==clientId);
            return Mapper.Map<IList<ClientLink>, IList<ClientLinkDto>>(clients.ToList());
        }
        public ClientLinkDto GetClientLink(Guid clientId)
        {
            var client = this._clientItemRepository.Get(c => c.Id == clientId);
            return Mapper.Map<ClientLink, ClientLinkDto>(client);
        }


        public void DeleteClient(Guid clientId)
        {
            var clientInfo = this._clientRepository.GetByKey(clientId);
            clientInfo.ClientLinks.Each(c => c.SetDeleteState());
            clientInfo.SetDeleteState();
            this._clientRepository.Update(clientInfo);
            this.Context.Commit();
        }

        public void DeleteClient(IList<Guid> clientLinkIds)
        {
            var clientLinks = this._clientItemRepository.GetAll(c => clientLinkIds.Contains(c.Id));
            clientLinks.Each(c => c.SetDeleteState());
            this._clientItemRepository.Update(clientLinks);
            this.Context.Commit();
        }



        public IList<AddressAreaDto> GetAddressAreas(int parentId)
        {
           // System.Linq.Expressions.Expression<Func<AddressArea,bool>> specfily=;
            IEnumerable<AddressArea> clients;
            if (parentId == 0)
            {
                clients = this._addressAreaRepository.GetAll(d => d.ParentId == d.AddressAreaID);
            }
            else
            { 
                clients = this._addressAreaRepository.GetAll(d =>d.ParentId!=d.AddressAreaID && d.ParentId ==parentId );
            }
           return Mapper.Map<IList<AddressArea>, IList<AddressAreaDto>>(clients.ToList());
        }


        public IList<AddressAreaDto> GetAddressAllAreas()
        {
            var clients = this._addressAreaRepository.GetAll();
            return Mapper.Map<IList<AddressArea>, IList<AddressAreaDto>>(clients.ToList());
        }


        public ClientInfoDto GetClientInfo(Guid clientId)
        {
            var client = this._clientRepository.GetByKey(clientId);
            client.ResponsiblePerson=client.ResponsiblePerson??new User();
          
            return Mapper.Map<ClientInfo, ClientInfoDto>(client);
        }





      
    }
}
